package com.panda.web.service.order.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.panda.common.core.domain.AjaxResult;
import com.panda.common.core.domain.R;
import com.panda.web.configuration.WeChatConfig;
import com.panda.web.domain.dto.OrderDTO;
import com.panda.web.domain.vo.OrderCount;
import com.panda.web.domain.vo.OrderVO;
import com.panda.web.entity.order.WechatOrder;
import com.panda.web.entity.product.OpenidProduct;
import com.panda.web.entity.wechat.WechatUser;
import com.panda.web.entity.wechatinfo.UserMajorRgpp;
import com.panda.web.entity.wechatinfo.WechatUserinfo;
import com.panda.web.excel.domain.OrderExcel;
import com.panda.web.mapper.order.WechatOrderMapper;
import com.panda.web.mapper.product.OpenidProductMapper;
import com.panda.web.mapper.wechat.WechatUserMapper;
import com.panda.web.mapper.wechatinfo.UserMajorRgppMapper;
import com.panda.web.mapper.wechatinfo.WechatUserinfoMapper;
import com.panda.web.service.order.IWechatOrderService;

import com.panda.web.utils.XmlUtils;

import com.panda.web.utils.payutils.WXRefundOrderRespVO;
import com.wechat.pay.contrib.apache.httpclient.exception.WechatPayException;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;

import com.wechat.pay.java.service.refund.model.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jdom2.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;

import java.io.*;
import java.math.BigDecimal;
import java.rmi.RemoteException;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import lombok.extern.slf4j.Slf4j;
import com.panda.web.utils.pageutils.PageResult;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import static com.wechat.pay.java.core.http.Constant.*;


/**
 * 微信支付订单Service业务层处理
 *
 * @author cpanda
 * @date 2025-02-27
 */
@Slf4j
@Service
public class WechatOrderServiceImpl extends ServiceImpl<WechatOrderMapper, WechatOrder> implements IWechatOrderService {
    @Autowired
    WechatOrderMapper orderMapper;
    @Autowired
    WeChatConfig config;
    @Autowired
    XmlUtils xmlUtils;
    @Autowired
    OpenidProductMapper openidProductMapper;
    @Autowired
    WechatUserMapper wechatUserMapper;
    @Autowired
    WechatUserinfoMapper userinfoMapper;
    @Autowired
    UserMajorRgppMapper userMajorRgppMapper;

    private static final String TRADE_TYPE = "JSAPI";
    // 退款 API 地址

    private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    @Override
    public Map<String, String> createOrder(WechatOrder order) throws Exception {
        String openid = order.getOpenid();
        String orderId = generateOrderNo(config.getMerchantId());
        String outTradeNo = orderId;

        Map<String, String> params = new HashMap<>();
        params.put("appid", config.appId);
        params.put("mch_id", config.merchantId);
        params.put("nonce_str", generateNonceStr());
        params.put("body", "Test Product");
        params.put("out_trade_no", outTradeNo);
        params.put("total_fee", String.valueOf(order.getTotalFee().multiply(new BigDecimal(100)).intValue()));//微信分计算
        params.put("notify_url", config.notifyUrl);
        params.put("trade_type", TRADE_TYPE);
        params.put("openid", openid);

        String sign = generateSignature(params, config.getApiV3Key());
        params.put("sign", sign);

        String xmlData = mapToXml(params);

        String response = sendPostRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", xmlData);
        System.out.println("Response: " + response);
        // 将 XML 字符串转换为 JsonNode 对象
// 5. 解析微信支付返回的 XML 响应
        Map<String, String> responseMap = parseXml(response);
        String returnCode = responseMap.get("return_code");
        String resultCode = responseMap.get("result_code");

        // 6. 检查返回结果
        if (!"SUCCESS".equals(returnCode)) {
            throw new Exception("微信支付请求失败: " + responseMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(resultCode)) {
            throw new Exception("微信支付业务失败: " + responseMap.get("err_code_des"));
        }

        // 7. 提取 prepay_id
        String prepayId = responseMap.get("prepay_id");

        // 8. 存储订单信息到数据库
        WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
        if (wechatUser != null) {
            if (!Objects.equals(wechatUser.getNickname(), null)) {
                order.setNickName(wechatUser.getNickname());
            }
        }
        order.setOrderId(orderId);
        order.setOutTradeNo(orderId);
        order.setTransactionId(prepayId); // 设置微信支付订单号
        order.setPayStatus("待支付"); // 设置支付状态
        order.setPayTime(new Date()); // 设置支付时间
        order.setCreateTime(new Date()); // 设置创建时间
        orderMapper.insert(order); // 插入订单到数据库

        // 9. 生成支付参数
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000); // 当前时间戳
        String nonceStr = generateNonceStr(); // 随机字符串
        String packageStr = "prepay_id=" + prepayId; // package 参数
        String signType = "MD5"; // 签名类型

        // 10. 生成签名
        Map<String, String> payParams = new HashMap<>();
        payParams.put("appId", config.appId);
        payParams.put("timeStamp", timeStamp);
        payParams.put("nonceStr", nonceStr);
        payParams.put("package", packageStr);
        payParams.put("signType", signType);

        String paySign = generateSignature(payParams, config.getApiV3Key());
        payParams.put("paySign", paySign);

        // 11. 返回支付参数给前端
        return payParams;
    }


    private String generateOrderNo(String merId) {
        // 生成商户订单号
        // 获取当前时间戳（精确到秒）
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        // 生成一个随机数，用于防止同一秒内生成重复的订单号
        Random random = new Random();
        int randomNum = random.nextInt(1000);  // 生成 3 位随机数

        // 格式化成固定长度，不足补零
        String randomStr = String.format("%03d", randomNum);

        // 拼接商户订单号（商户编号 + 时间戳 + 随机数）
        String orderNumber = merId + timestamp + randomStr;

        return orderNumber;
    }


    /**
     * 新增订单
     *
     * @param dto
     * @return
     */
    @Override
    public int insert(OrderDTO dto) {
        WechatOrder order = new WechatOrder();
        BeanUtils.copyProperties(dto, order);
        orderMapper.insert(order);
        return 1;
    }

    @Override
    public PageResult<OrderVO> ListText(OrderDTO dto, Integer pageNum, Integer pageSize) {
        Page<OrderVO> page = new Page<>(pageNum, pageSize);
        IPage<OrderVO> houseIPage = orderMapper.selectOrderPage(page, dto);
        List<OrderVO> records = houseIPage.getRecords();
        orderFyList(records);
        return new PageResult<>(records, houseIPage.getTotal(), pageNum, pageSize);
    }

    /**
     * 分页查询
     *
     * @param dto
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<OrderVO> PageList(OrderDTO dto, Integer pageNum, Integer pageSize) {

        Page<WechatOrder> page = new Page<>(pageNum, pageSize);
        QueryWrapper<WechatOrder> queryWrapper = new QueryWrapper();//需要处理查询条件
        if (!Objects.equals(dto.getNickName(), null)) {
            queryWrapper.like("nick_name", dto.getNickName());
        }
        if (!Objects.equals(dto.getStartTime(), null) && !Objects.equals(dto.getEndTime(), null)) {
            String startTime = convertToDateTime(dto.getStartTime(), false);
            String endTime = convertToDateTime(dto.getEndTime(), true);
            queryWrapper.between("pay_time", startTime, endTime);
        }

        queryWrapper.eq("pay_status", "已支付");
        queryWrapper.orderByDesc("pay_time");
        IPage<WechatOrder> orderIPage = orderMapper.selectPage(page, queryWrapper);
        long total = orderIPage.getTotal();
        List<WechatOrder> records = orderIPage.getRecords();
        List<OrderVO> voList = orderVoToList(records);//封装vo数据方法

        return new PageResult<>(voList, total, pageNum, pageSize);
    }

    @Override
    public PageResult<OrderVO> refundList(OrderDTO dto, Integer pageNum, Integer pageSize) {

        Page<WechatOrder> page = new Page<>(pageNum, pageSize);
        QueryWrapper<WechatOrder> queryWrapper = new QueryWrapper();//需要处理查询条件
        if (!Objects.equals(dto.getNickName(), null)) {
            queryWrapper.like("nick_name", dto.getNickName());
        }
        if (!Objects.equals(dto.getRefundStatus(), null)) {
            queryWrapper.like("refund_status", dto.getRefundStatus());
        }
        queryWrapper.eq("refund_status", "全部退款").or().eq("refund_status", "部分退款");
        queryWrapper.orderByDesc("refund_time");
        IPage<WechatOrder> orderIPage = orderMapper.selectPage(page, queryWrapper);
        long total = orderIPage.getTotal();
        List<WechatOrder> records = orderIPage.getRecords();
        List<OrderVO> voList = orderVoToList(records);//封装vo数据方法

        return new PageResult<>(voList, total, pageNum, pageSize);
    }

    @Override
    public List<OrderExcel> exportList(OrderDTO dto) {
        QueryWrapper<WechatOrder> queryWrapper = new QueryWrapper();//需要处理查询条件
        if (!Objects.equals(dto.getNickName(), null)) {
            queryWrapper.like("nick_name", dto.getNickName());
        }
        if (!Objects.equals(dto.getStartTime(), null) && !Objects.equals(dto.getEndTime(), null)) {
            String startTime = convertToDateTime(dto.getStartTime(), false);
            String endTime = convertToDateTime(dto.getEndTime(), true);
            queryWrapper.between("pay_time", startTime, endTime);
        }
        queryWrapper.eq("pay_status", "已支付");

        queryWrapper.orderByDesc("pay_time");
        List<WechatOrder> orderList = orderMapper.selectList(queryWrapper);
        List<OrderExcel> voList = orderExcelList(orderList);//封装vo数据方法
        return voList;
    }

    @Override
    public OrderCount getOrderCount(OrderDTO dto) {
        OrderCount count = new OrderCount();
        QueryWrapper<WechatOrder> queryWrapper = new QueryWrapper();//需要处理查询条件
        if (!Objects.equals(dto.getNickName(), null)) {
            queryWrapper.like("nick_name", dto.getNickName());
        }
        if (!Objects.equals(dto.getStartTime(), null) && !Objects.equals(dto.getEndTime(), null)) {
            String startTime = convertToDateTime(dto.getStartTime(), false);
            String endTime = convertToDateTime(dto.getEndTime(), true);
            queryWrapper.between("pay_time", startTime, endTime);
        }
        queryWrapper.eq("pay_status", "已支付");
        queryWrapper.orderByDesc("pay_time");
        queryWrapper.ne("refund_status", "全部退款").or().eq("refund_status", "部分退款");
        List<WechatOrder> orderList = orderMapper.selectList(queryWrapper);
        BigDecimal amount = orderList.stream().map(WechatOrder::getTotalFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal onlineAmount = orderList.stream().filter(o -> Objects.equals(o.getOrderType(), "0")).map(WechatOrder::getTotalFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal offlineAmount = orderList.stream().filter(o -> Objects.equals(o.getOrderType(), "1")).map(WechatOrder::getTotalFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        count.setAmount(amount);
        count.setOnlineAmount(onlineAmount);
        count.setOfflineAmount(offlineAmount);
        return count;
    }


    //根据传入的 yyyy-MM-dd 类型的开始结束时间  ，返回 yyyy-MM-dd HH:mm:ss 类型的开始结束时间
    public String convertToDateTime(String date, boolean isEndTime) {
        LocalDateTime localDateTime = LocalDate.parse(date).atStartOfDay(); // 默认将日期转为 00:00:00
        if (isEndTime) {//true 返回结束时间
            localDateTime = localDateTime.withHour(23).withMinute(59).withSecond(59); // 如果是结束时间，设置为 23:59:59
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return localDateTime.format(formatter);  // 格式化为所需的字符串
    }

    /**
     * 无分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public List<OrderVO> choiceList(OrderDTO dto) {
        QueryWrapper<WechatOrder> queryWrapper = new QueryWrapper();//需要处理查询条件
        if (!Objects.equals(dto.getNickName(), null)) {
            queryWrapper.like("nick_name", dto.getNickName());
        }
        if (!Objects.equals(dto.getStartTime(), null) && !Objects.equals(dto.getEndTime(), null)) {
            String startTime = convertToDateTime(dto.getStartTime(), false);
            String endTime = convertToDateTime(dto.getEndTime(), true);
            queryWrapper.between("pay_time", startTime, endTime);
        }
        queryWrapper.eq("pay_status", "已支付");
        queryWrapper.orderByDesc("pay_time");
        List<WechatOrder> orderList = orderMapper.selectList(queryWrapper);
        List<OrderVO> voList = orderVoToList(orderList);//封装vo数据方法
        return voList;
    }

    /**
     * 回显数据
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderVO selectById(Long orderId) {
        OrderVO vo = new OrderVO();
        WechatOrder order = orderMapper.selectById(orderId);
        BeanUtils.copyProperties(order, vo);
        return vo;
    }


    /**
     * 修改数据
     *
     * @param dto
     * @return
     */
    @Override
    public int updateOrderById(OrderDTO dto) {
        WechatOrder order = new WechatOrder();
        BeanUtils.copyProperties(dto, order);
        orderMapper.updateById(order);
        return 1;
    }

    /**
     * 删除数据(逻辑删除)
     *
     * @param ids
     * @return
     */
    @Override
    public int removeByOrderIds(List<Long> ids) {
        for (Long id : ids) {
            WechatOrder order = orderMapper.selectById(id);
            orderMapper.updateById(order);
        }
        return 1;
    }

    /**
     * 微信jsapi支付退款
     *
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public synchronized int refundOrder(OrderDTO dto) {
        String orderId = dto.getOrderId();
        WechatOrder order = orderMapper.findByOrderId(orderId);
        if (Objects.equals(order.getTransactionId(), null)) {
            throw new RuntimeException("订单未支付");
        }
        if (Objects.equals(order.getRefundStatus(), "已退款")) {
            throw new RuntimeException("该订单已退款,无法重复退款");
        }
        try {
            // 使用自动更新平台证书的RSA配置
//            // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错

            // 构建退款service
            RefundService service = new RefundService.Builder().config(config.getConfig()).build();
            // request.setXxx(val)设置所需参数，具体参数可见Request定义
            //构建退款请求
            CreateRequest request = new CreateRequest();
            request.setTransactionId(order.getTransactionId());
            //构建订单金额信息
            AmountReq amountReq = new AmountReq();
            //退款金额
            amountReq.setRefund(dto.getRefundFee().multiply(new BigDecimal(100)).longValue());
            //原订单金额
            amountReq.setTotal(order.getTotalFee().multiply(new BigDecimal(100)).longValue());
            //货币类型(默认人民币)
            amountReq.setCurrency("CNY");
            request.setAmount(amountReq);
            //商户退款单号
            request.setOutRefundNo(generateRefundNo());
            //退款通知回调地址
            request.setNotifyUrl(config.returnUrl);
            // 调用退款方法，得到应答
            // 调用微信sdk接口
            Refund refund = service.create(request);
            //接收退款返回参数
            Refund refundResponse = new Refund();
            refundResponse.setStatus(refund.getStatus());
            if (refundResponse.getStatus().equals(Status.SUCCESS)) {
                log.info(order.getTransactionId() + " 退款成功");
            } else if (refundResponse.getStatus().equals(Status.PROCESSING)) {
                log.info(order.getTransactionId() + " 退款处理中");
            } else if (refundResponse.getStatus().equals(Status.CLOSED)) {
                log.info(order.getTransactionId() + "退款关闭");
            } else {
                log.info(order.getTransactionId() + "退款异常");
            }
        } catch (ServiceException e) {
            JSONObject parse = JSONObject.parseObject(e.getResponseBody());
            throw new RuntimeException(parse.getString("message"));
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }
        return 1;
    }

    /**
     * 退款回调通知
     *
     * @param request
     */
    @Override
    public int refundNotify(HttpServletRequest request) throws IOException {

        //读取请求体的信息
        ServletInputStream inputStream = request.getInputStream();
        StringBuffer stringBuffer = new StringBuffer();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s;
        //读取回调请求体
        while ((s = bufferedReader.readLine()) != null) {
            stringBuffer.append(s);
        }
        String s1 = stringBuffer.toString();
        String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
        String nonce = request.getHeader(WECHAT_PAY_NONCE);
        String signType = request.getHeader("Wechatpay-Signature-Type");
        String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
        String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
        // 如果已经初始化了 config，可直接使用
        // 没有的话，则构造一个


//            NotificationConfig configA = new RSAAutoCertificateConfig.Builder()
//                    .merchantId(config.getMerchantId())
//                    .privateKeyFromPath(config.getPrivateKeyPath())
//                    .merchantSerialNumber(config.getMerchantSerialNumber())
//                    .apiV3Key(config.getApiV3Key())
//                    .build();
//            log.error(JSON.toJSONString(configA));
        NotificationParser parser = new NotificationParser((NotificationConfig) config.getConfig());
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serialNo)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                // 若未设置signType，默认值为 WECHATPAY2-SHA256-RSA2048
                .signType(signType)
                .body(s1)
                .build();
        RefundNotification parse = parser.parse(requestParam, RefundNotification.class);
        log.info(parse + "aaaaaaaaaaaaa");
        String refundId = parse.getRefundId();
        String outRefundNo = parse.getOutRefundNo();
        String outTradeNo = parse.getOutTradeNo();
        String successTime = parse.getSuccessTime();
        Amount amount = parse.getAmount();
        Long total = amount.getTotal();//总金额
        Long refund = amount.getRefund();//退款金额

        String userReceivedAccount = parse.getUserReceivedAccount();//退回位置

        BigDecimal refundFee = new BigDecimal(refund).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);

        WechatOrder wechatOrder = orderMapper.findByOrderId(outTradeNo);
        wechatOrder.setRefundId(refundId);
        wechatOrder.setRefundOrderId(outRefundNo);
        if (wechatOrder.getRefundFee().add(refundFee).compareTo(wechatOrder.getTotalFee()) == 0) {
            wechatOrder.setRefundStatus("全部退款"); //TODO  实现可部分退款
            wechatOrder.setRefundFee(wechatOrder.getRefundFee().add(refundFee));

            OpenidProduct openidProduct = openidProductMapper.findByProductIdAndOpenId(wechatOrder.getOpenid(), wechatOrder.getProductId());
            if (openidProduct != null) {
                openidProduct.setStatus("1");//停用
                openidProductMapper.updateById(openidProduct);
            }
        } else if (wechatOrder.getRefundFee().add(refundFee).compareTo(wechatOrder.getTotalFee()) < 0) {
            wechatOrder.setRefundStatus("部分退款"); //实现可部分退款
            wechatOrder.setRefundFee(wechatOrder.getRefundFee().add(refundFee));
        } else if (wechatOrder.getRefundFee().add(refundFee).compareTo(wechatOrder.getTotalFee()) > 0) {
            throw new RemoteException("退款金额大于订单金额，无法退款");
        }
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(simpleDateFormat);
        wechatOrder.setRefundTime(format);
        wechatOrder.setSuccessTime(successTime);
        wechatOrder.setUserReceivedAccount(userReceivedAccount);

        orderMapper.updateById(wechatOrder);


        // 解析 JSON 字符串
        if (Objects.equals(parse.getRefundStatus(), "SUCCESS")) {
            log.info(parse.getRefundStatus() + " eeeeeeeeee"); //-
        }
        log.info(parse.getRefundStatus() + " BBBBBBBBBBBBBBBBBB"); //-
        //parse.getRefundStatus().equals("SUCCESS");说明退款成功
        return 1;
    }


    // 生成退款单号，通常是时间戳加上商户订单号的一部分
    private String generateRefundNo() {
        return System.currentTimeMillis() + "REFUND"; // 可以根据需要自行生成退款单号
    }


    /**
     * 解析 XML 字符串为 Map
     */
    private Map<String, String> parseXml(String xml) throws Exception {
        Map<String, String> resultMap = new HashMap<>();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")));
        Element root = document.getDocumentElement();
        NodeList nodeList = root.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            if (nodeList.item(i) instanceof Element) {
                Element element = (Element) nodeList.item(i);
                resultMap.put(element.getNodeName(), element.getTextContent());
            }
        }
        return resultMap;
    }

    // 生成退款单号
    public static String generateRefundNo(String orderNo) {
        // 使用订单号和时间戳组合生成退款单号
        return orderNo + "_refund_" + System.currentTimeMillis();
    }

    private void orderFyList(List<OrderVO> voList) {

        if (voList.size() > 0 && !voList.isEmpty()) {
            for (OrderVO order : voList) {
                if (Objects.equals(order.getOrderType(), "0")) {
                    order.setOrderType("线上付款");
                } else {
                    order.setOrderType("后台开通");
                }
                String openid = order.getOpenid();
                WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
                if (wechatUser != null) {
                    order.setNickName(wechatUser.getNickname());
                }
                WechatUserinfo userinfo = userinfoMapper.findByOpenid(openid);
                if (userinfo != null) {
                    order.setName(userinfo.getName());
                    if (userinfo.getUnderstand() != null) {
                        order.setUnderstand(userinfo.getUnderstand());
                    }
                    order.setBackground(userinfo.getBackground());
                    String graduateTime = userinfo.getGraduateTime();
                    String currentYear = String.valueOf(LocalDate.now().getYear());  // 获取当前年份
                    String graduateYear = graduateTime.split("-")[0];
                    String lastTwoDigits = graduateYear.substring(2); // 取后两位
                    int month = LocalDate.now().getMonthValue();  // 获取当前年月份
                    if (month<7){
                        if (Integer.parseInt(graduateYear) > Integer.parseInt(currentYear)) {//实习
                            order.setGraduate(lastTwoDigits + "实习");
                        } else if (Integer.parseInt(graduateYear) == Integer.parseInt(currentYear)) {
                            order.setGraduate(lastTwoDigits + "校招");
                        } else {//社招
                            order.setGraduate(lastTwoDigits + "社招");
                        }
                    }else {
                        if (Integer.parseInt(graduateYear) > Integer.parseInt(currentYear)+1) {//实习
                            order.setGraduate(lastTwoDigits + "实习");
                        } else if (Integer.parseInt(graduateYear) == Integer.parseInt(currentYear)+1) {
                            order.setGraduate(lastTwoDigits + "校招");
                        } else {//社招
                            order.setGraduate(lastTwoDigits + "社招");
                        }
                    }

                    List<UserMajorRgpp> userMajorRgppList = userMajorRgppMapper.findByOpenid(openid);
                    if (userMajorRgppList != null && !userMajorRgppList.isEmpty()) {
                        String major = "";
                        for (UserMajorRgpp majorRgpp : userMajorRgppList) {
                            String majorName = majorRgpp.getMajorName();
                            String[] parts = majorName.split("-");
                            if (parts.length == 2 && !parts[1].isEmpty()) {
                                // 如果有两个部分且第二部分非空
                                major = major + parts[1] + " ";
                            } else if (parts.length == 3 && !parts[2].isEmpty()) {
                                // 如果有三个部分且第三部分非空
                                major = major + parts[2] + " ";
                            } else {
                                // 其他情况（例如 A-- 或 A）
                                major = major + parts[0] + " ";
                            }
                        }
                        order.setMajorName(major);
                    }
                }
            }
        }
    }

    // 处理VO数据封装
    private List<OrderVO> orderVoToList(List<WechatOrder> orderList) {
        List<OrderVO> voList = new ArrayList<>();
        if (orderList.size() > 0 && !orderList.isEmpty()) {
            for (WechatOrder order : orderList) {
                OrderVO vo = new OrderVO();
                BeanUtils.copyProperties(order, vo);
                if (Objects.equals(order.getOrderType(), "0")) {
                    vo.setOrderType("线上付款");
                } else {
                    vo.setOrderType("后台开通");
                }
                String openid = order.getOpenid();
                WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
                if (wechatUser != null) {
                    vo.setNickName(wechatUser.getNickname());
                }
                WechatUserinfo userinfo = userinfoMapper.findByOpenid(openid);
                if (userinfo != null) {
                    vo.setName(userinfo.getName());
                    if (userinfo.getUnderstand() != null) {
                        vo.setUnderstand(userinfo.getUnderstand());
                    }
                    vo.setBackground(userinfo.getBackground());
                    String graduateTime = userinfo.getGraduateTime();
                    String currentYear = String.valueOf(LocalDate.now().getYear());  // 获取当前年份
                    String graduateYear = graduateTime.split("-")[0];
                    String lastTwoDigits = graduateYear.substring(2); // 取后两位
                    if (Integer.parseInt(graduateYear) > Integer.parseInt(currentYear)) {//实习
                        vo.setGraduate(lastTwoDigits + "实习");
                    } else if (Integer.parseInt(graduateYear) == Integer.parseInt(currentYear)) {
                        vo.setGraduate(lastTwoDigits + "校招");
                    } else {//社招
                        vo.setGraduate(lastTwoDigits + "社招");
                    }

                    List<UserMajorRgpp> userMajorRgppList = userMajorRgppMapper.findByOpenid(openid);
                    if (userMajorRgppList != null && !userMajorRgppList.isEmpty()) {
                        String major = "";
                        for (UserMajorRgpp majorRgpp : userMajorRgppList) {
                            String majorName = majorRgpp.getMajorName();
                            String[] parts = majorName.split("-");
                            if (parts.length == 2 && !parts[1].isEmpty()) {
                                // 如果有两个部分且第二部分非空
                                major = major + parts[1] + " ";
                            } else if (parts.length == 3 && !parts[2].isEmpty()) {
                                // 如果有三个部分且第三部分非空
                                major = major + parts[2] + " ";
                            } else {
                                // 其他情况（例如 A-- 或 A）
                                major = major + parts[0] + " ";
                            }
                        }
                        vo.setMajorName(major);
                    }


                }
                voList.add(vo);
            }
        }
        return voList;
    }

    private List<OrderExcel> orderExcelList(List<WechatOrder> orderList) {
        List<OrderExcel> voList = new ArrayList<>();
        if (orderList.size() > 0 && !orderList.isEmpty()) {
            for (WechatOrder order : orderList) {
                OrderExcel vo = new OrderExcel();
                BeanUtils.copyProperties(order, vo);
                if (Objects.equals(order.getOrderType(), "0")) {
                    vo.setOrderType("线上付款");
                } else {
                    vo.setOrderType("后台开通");
                }
                String openid = order.getOpenid();
                WechatUserinfo userinfo = userinfoMapper.findByOpenid(openid);
                if (userinfo != null) {
                    vo.setName(userinfo.getName());
                    if (userinfo.getUnderstand() != null) {
                        vo.setUnderstand(userinfo.getUnderstand());
                    }

                    vo.setPayTime(new SimpleDateFormat("yyyy-MM-dd").format(order.getPayTime()));
                    vo.setBackground(userinfo.getBackground());
                    String graduateTime = userinfo.getGraduateTime();
                    String currentYear = String.valueOf(LocalDate.now().getYear());  // 获取当前年份
                    String graduateYear = graduateTime.split("-")[0];
                    String lastTwoDigits = graduateYear.substring(2); // 取后两位
                    if (Integer.parseInt(graduateYear) > Integer.parseInt(currentYear)) {//实习
                        vo.setGraduate(lastTwoDigits + "实习");
                    } else if (Integer.parseInt(graduateYear) == Integer.parseInt(currentYear)) {
                        vo.setGraduate(lastTwoDigits + "校招");
                    } else {//社招
                        vo.setGraduate(lastTwoDigits + "社招");
                    }

                    List<UserMajorRgpp> userMajorRgppList = userMajorRgppMapper.findByOpenid(openid);
                    if (userMajorRgppList != null && !userMajorRgppList.isEmpty()) {
                        String major = "";
                        for (UserMajorRgpp majorRgpp : userMajorRgppList) {
                            String majorName = majorRgpp.getMajorName();
                            String[] parts = majorName.split("-");
                            if (parts.length == 2 && !parts[1].isEmpty()) {
                                // 如果有两个部分且第二部分非空
                                major = major + parts[1] + " ";
                            } else if (parts.length == 3 && !parts[2].isEmpty()) {
                                // 如果有三个部分且第三部分非空
                                major = major + parts[2] + " ";
                            } else {
                                // 其他情况（例如 A-- 或 A）
                                major = major + parts[0] + " ";
                            }
                        }
                        vo.setMajorName(major);
                    }


                }
                voList.add(vo);
            }
        }
        return voList;
    }

    private static String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }

    private static String generateSignature(Map<String, String> params, String apiKey) throws Exception {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            sb.append(key).append("=").append(params.get(key)).append("&");
        }
        sb.append("key=").append(apiKey);

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(sb.toString().getBytes("UTF-8"));
        return byteArrayToHexString(digest).toUpperCase();
    }

    private static String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    private static String mapToXml(Map<String, String> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append("<").append(entry.getKey()).append(">");
            sb.append(entry.getValue());
            sb.append("</").append(entry.getKey()).append(">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    private static String sendPostRequest(String url, String xmlData) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(xmlData, "UTF-8"));
            httpPost.setHeader("Content-Type", "application/xml");

            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, "UTF-8");
        }
    }

    /**
     * description: 解析微信通知xml
     *
     * @param xml
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    @SuppressWarnings({"unused", "rawtypes", "unchecked"})
    public static Map parseXmlToList(String xml) {
        Map retMap = new HashMap();
        try {
            StringReader read = new StringReader(xml);
            // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
            InputSource source = new InputSource(read);
            // 创建一个新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通过输入源构造一个Document
            org.jdom2.Document doc = (org.jdom2.Document) sb.build(source);
            org.jdom2.Element root = doc.getRootElement();// 指向根节点
            List<org.jdom2.Element> es = root.getChildren();
            if (es != null && es.size() != 0) {
                for (org.jdom2.Element element : es) {
                    retMap.put(element.getName(), element.getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retMap;

    }
}